package mt.comm;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import mt.comm.ServerSideMessage.Type;

/**
 * This class allows each connected client to maintain a connection with the server. It has a running listening Thread for each
 * of the clients, and it also enables to send ClientSideMessages to the clients in response to their requests.
 * 
 * @author Nuno Santos
 *
 */
public class ClientThread implements Runnable {

	private Socket clientSocket;
	private String nickname;
	private Thread clientThread;
	private ObjectOutputStream clientOutputStream;
	private ObjectInputStream clientInputStream;
	private CommunicationsServer server;

	/**
	 * Creates a ClientThread. Requires the client socket and the server to which it is connected
	 * 
	 * @param clientSocket
	 * @param communicationsServer
	 */
	public ClientThread(Socket clientSocket, CommunicationsServer communicationsServer){
		this.clientSocket = clientSocket;
		this.server = communicationsServer;
	}

	/**
	 * Returns the nickname of the client
	 * @return nickname
	 */
	public String getNickname(){
		return nickname;
	}

	/**
	 * Starts the Client Thread
	 */
	public void start(){
		try {
			clientInputStream = new ObjectInputStream(clientSocket.getInputStream());
			clientOutputStream = new ObjectOutputStream(clientSocket.getOutputStream());

			clientThread = new Thread(this);
			clientThread.start();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Thread listening to messages from the client to the server
	 */
	@Override
	public void run() {
		boolean disconnect = false;
		ServerSide message= null;
		while(!disconnect){
			try {
				message = (ServerSide) clientInputStream.readObject();

				server.addToQueue(message);

				if(message.getType() == Type.CONNECTED)
					nickname = message.getSenderNickname();

				System.out.println("Servidor recebeu mensagem de: " + nickname + " de tipo: " + message.getType());

				if(message.getType() == Type.DISCONNECTED){
					disconnect = true;
					server.disconnectClient(nickname);
				}

			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
			}

		}

	}

	/**
	 * Sends a message from the server to the client
	 * @param message
	 */
	public void messageSending(ClientSide message){
		try {
			clientOutputStream.writeObject(message);
			clientOutputStream.reset();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Disconnects this client from the server
	 */
	public void disconnect(){
		try {
			clientOutputStream.flush();
			clientOutputStream.close();
			clientInputStream.close();
			//			clientSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
